﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.ComponentModel;

namespace ProgNetComponentsDx.Components
{
    public abstract class BaseBgAppender : Component, IDisposable
    {
        #region Fields
        List<string> lines = new List<string>();
        private int _AppendInterval;
        private Timer timer;
        #endregion

        #region events
        public event EventHandler LinesAppended;
        #endregion

        #region properties
        public bool LockAppending
        {
            get;
            set;
        }
        public int LinesPack
        {
            get;
            set;
        }
        public int SleepTimeAfterAppend
        {
            get;
            set;
        }
        public int AppendInterval
        {
            get { return _AppendInterval; }
            set
            {
                _AppendInterval = value;
                if (_AppendInterval > 0)
                {
                    timer.Interval = value;
                }
            }
        }
        #endregion

        #region CTOR
        protected BaseBgAppender()
        {
            timer = new Timer();
            timer.Tick += new EventHandler(timer_Tick);
            LinesPack = 20;
            AppendInterval = 100;
            SleepTimeAfterAppend = 50;
        }
        #endregion

        #region private impl
        private void timer_Tick(object sender, EventArgs e)
        {
            if (AppendInterval > 0)
            {
                AppendLines();
            }
        }
       
        private void AppendLines()
        {
            if (lines.Count > 0 && !LockAppending)
            {
                string[] s = lines.ToArray();
                lines.Clear();

                AppendFullLines(GetFullLines(s));
                if (LinesAppended != null)
                    LinesAppended(this, EventArgs.Empty);
            }
        }

        #endregion

        protected virtual string GetFormatedLine(string text)
        {
            if (text != null)
            {
                text = text.ReplaceDoubleEOL();
                if (!text.EndsWith("\n"))
                    text += "\n";
            }
            return text;
        }
        protected virtual string GetFullLines(string[] lines)
        {
            StringBuilder str = new StringBuilder();
            
            foreach (string l in lines)
                str.Append(l);

            return str.ToString().ReplaceSingleEOL();
        }
        protected abstract void AppendFullLines(string fullLines);

        public bool Append(string text)
        {
            if (text != null)
            {
                text = GetFormatedLine(text);
                lines.Add(text);
                if (LinesPack > 0 && lines.Count >= LinesPack)
                {
                    AppendLines();
                    if (SleepTimeAfterAppend > 0)
                    {
                        System.Threading.Thread.Sleep(SleepTimeAfterAppend);
                    }
                    return true;
                }
            }
            return false;
        }
        public virtual void Finish()
        {
            LockAppending = false;
            AppendLines();
            timer.Stop();
        }
        public virtual void Start()
        {
            lines.Clear();
            timer.Start();
        }

        #region IDisposable Members

        protected override void Dispose(bool disposing)
        {
            timer.Stop();
            timer.Dispose();
            base.Dispose(disposing);
        }

        #endregion
    }
}
